using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using WindowsGame1.Helpers;

namespace WindowsGame1
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Game
    {
// ReSharper disable UnaccessedField.Local
        GraphicsDeviceManager _graphicsDevice;
// ReSharper restore UnaccessedField.Local
        SpriteBatch _spriteBatch;
        public static Texture2D SpriteTexture;

        readonly MouseHelper _mouse = new MouseHelper();
        private int _delayCounter;

        private Tile _selectedTile;

        const int Tilesize = 25;

        public List<Tile> Tiles = new List<Tile>();
        public List<Action> ActionList = new List<Action>();
        public List<Worker> Workers = new List<Worker>();

        public Game1()
        {
            
            _graphicsDevice = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here
            IsMouseVisible = true;
            
            for (int x = 0; x < 20; x++)
            {
                for (int y = 0; y < 20; y++)
                {
                    Tiles.Add(new Tile
                                  {
                                      Rectangle = new Rectangle(x * Tilesize, y * Tilesize, Tilesize - 1, Tilesize - 1) , 
                                      Color = Color.Brown
                                  }); 
                }
            }
            for (int x = 0; x < 3; x++)
            {
                Workers.Add(new Worker
                                {
                                    Destination = new Vector2(10*Tilesize, 10*Tilesize),
                                    Tile = new Tile
                                               {
                                                   Rectangle = new Rectangle(0, 0, Tilesize - 1, Tilesize - 1),
                                                   Color = Color.Green
                                               },
                                    Actions = new List<Action>()
                                });
            }


            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            _spriteBatch = new SpriteBatch(GraphicsDevice);

            // TODO: use this.Content to load your game content here
            SpriteTexture = Content.Load<Texture2D>("whitepixel");
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }



        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
            {
                Exit();
            }

            HandleInput();
            AI();

            base.Update(gameTime);
        }

        private void HandleInput()
        {
            _mouse.UpdateMouse();
            DragTile();
            MouseClick();
        }


        private void MouseClick()
        {
            if (_mouse.MouseClicked)
            {
                MouseClickAction(_mouse.Mouse);

                _mouse.MouseClicked = false; 
            }
        }

        private void DragTile()
        {
            //if(_mouse.MouseDown)
            //{
            //    _selectedTile = GetTileFromLocation(_mouse.Mouse.X, _mouse.Mouse.Y);
            //    if(_selectedTile != null)
            //    {
            //        _mouse.MouseXOffset = _mouse.Mouse.X - _selectedTile.Rectangle.X;
            //        _mouse.MouseYOffset = _mouse.Mouse.Y - _selectedTile.Rectangle.Y;
            //    }
            //}
            //if (_mouse.MousePressed && _selectedTile != null)
            //{
            //    _selectedTile.Rectangle = new Rectangle(_mouse.Mouse.X - _mouse.MouseXOffset, _mouse.Mouse.Y - _mouse.MouseYOffset, _selectedTile.Rectangle.Width, _selectedTile.Rectangle.Height);
            //}
            //else
            //{
            //    _selectedTile = null;
            //}
        }

        private void MouseClickAction(MouseState mouse)
        {
            Tile tile = GetTileFromLocation(mouse.X, mouse.Y);
            if (tile != null)
            {
                if(tile.Color == Color.Gray || tile.Color == Color.LightGray)
                {
                    tile.Color = Color.SandyBrown;
                    ActionList.Add(new Action { Tile = tile, ActionType = ActionType.KnockDownWall });


                }
                else
                {
                    tile.Color = Color.LightGray;
                    ActionList.Add(new Action { Tile = tile, ActionType = ActionType.BuildWall });
                            
                }
            }
        }

        private Tile GetTileFromLocation(int x, int y)
        {
            return Tiles.FirstOrDefault(tile => tile.Rectangle.Contains(x, y));
        }

        private void AI()
        {
            CarryOutActions();
        }

        private void CarryOutActions()
        {
            UpdateActions();

            MoveWorkers();
        }

        private void UpdateActions()
        {
            foreach (var action in ActionList)
            {
                action.Age++;
            }
        }

        private void MoveWorkers()
        {
            int counter = 0;
            foreach (var worker in Workers)
            {
                if(ActionList.Count() <= counter)
                {
                    return;
                }
                Action action = ActionList[counter];
                counter++;
                var direction = new Vector2();
                if (worker.Tile.Rectangle.X == 0 && worker.Tile.Rectangle.Y == 0)
                {
                    worker.ReturnHome = false;
                }
                if (worker.ReturnHome)
                {
                    direction = Vector2.Normalize(new Vector2(0 - worker.Tile.Rectangle.X, 0 - worker.Tile.Rectangle.Y));
                }
                else
                {
                    if (action != null)
                    {   
                        if(worker.Actions.Count < 1)
                        {
                            //worker.Actions[0] = RequestNextAction();
                            worker.Actions.Add(action);
                        }
                        else
                        {
                            Action workerCurrentAction = worker.Actions.First();
                            if (worker.Tile.Rectangle.Intersects(workerCurrentAction.Tile.Rectangle))
                            {
                                workerCurrentAction.PercentComplete = workerCurrentAction.PercentComplete + 1;
                                if (workerCurrentAction.PercentComplete > 100)
                                {
                                    workerCurrentAction.Tile.Color = Color.Gray;
                                    ActionList.Remove(workerCurrentAction);
                                    worker.Actions.Remove(workerCurrentAction);
                                    worker.ReturnHome = true;
                                }
                            }
                            else
                            {
                                direction =
                                    Vector2.Normalize(new Vector2(workerCurrentAction.Tile.Rectangle.X - worker.Tile.Rectangle.X,
                                                                  workerCurrentAction.Tile.Rectangle.Y - worker.Tile.Rectangle.Y));
                            }
                        }

                    }
                }


                worker.Location = worker.Location + (direction * 2);
                worker.Tile.Rectangle = new Rectangle((int)worker.Location.X, (int)worker.Location.Y, worker.Tile.Rectangle.Width, worker.Tile.Rectangle.Height);

            }
        }

        //private Action RequestNextAction()
        //{

            
        //}

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.White);

            // TODO: Add your drawing code here
            _spriteBatch.Begin();


            foreach (var tile in Tiles)
            {
                _spriteBatch.Draw(SpriteTexture, tile.Rectangle, tile.Color);  
            }
            foreach (var worker in Workers)
            {
                _spriteBatch.Draw(SpriteTexture, worker.Tile.Rectangle, worker.Tile.Color);  

            }
            
            _spriteBatch.End();
            base.Draw(gameTime);
        }
    }
}
